package com.hopes.bizz.risk.gis.service.impl;

import cn.hutool.core.date.DateUtil;
import com.hopes.bizz.common.core.util.CollectionUtils;
import com.hopes.bizz.risk.common.constant.HidDicConstant;
import com.hopes.bizz.risk.common.constant.RiskDicConstant;
import com.hopes.bizz.risk.common.constant.enums.RiskSysDictEnum;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskRecordEntity;
import com.hopes.bizz.risk.control.entity.RiskObjectEntity;
import com.hopes.bizz.risk.control.service.RiskMeasureTaskRecordService;
import com.hopes.bizz.risk.control.service.RiskObjectService;
import com.hopes.bizz.risk.gis.constant.RiskHidCountStatisticsTypeEnum;
import com.hopes.bizz.risk.gis.constant.RiskStatisticsCycleEnum;
import com.hopes.bizz.risk.gis.helper.LineStatisticsHelper;
import com.hopes.bizz.risk.gis.service.GisService;
import com.hopes.bizz.risk.gis.vo.LineStatistics;
import com.hopes.bizz.risk.gis.vo.RiskHidCountStatistics;
import com.hopes.bizz.risk.gis.vo.RiskHidStatusStatistics;
import com.hopes.bizz.risk.gis.vo.RiskObjectLevelStatistics;
import com.hopes.bizz.risk.hid.entity.RiskHidHiddenDangerEntity;
import com.hopes.bizz.risk.hid.service.RiskHidHiddenDangerService;
import com.hopes.bizz.risk.transfer.service.RiskTransferAuthService;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.enums.AdminDictEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lyb
 * @version 1.0
 * @date 2024/2/23 10:22
 */
@Service
@Slf4j
@AllArgsConstructor
public class GisServiceImpl implements GisService {

    private final RiskObjectService riskObjectService;

    private final RiskHidHiddenDangerService riskHidHiddenDangerService;

    private final RiskTransferAuthService riskTransferAuthService;

    private final RiskMeasureTaskRecordService riskMeasureTaskRecordService;

    @Override
    public RiskObjectLevelStatistics calculateRiskObjectLevelStatistics() {
        RiskObjectLevelStatistics riskObjectLevelStatistics = new RiskObjectLevelStatistics();
        List<RiskObjectEntity> riskObjects = riskObjectService.lambdaQuery()
                .select(RiskObjectEntity::getRiskLevel)
                .list();
        Map<Integer, Long> riskLevelMap = riskObjects.stream().collect(Collectors.groupingBy(RiskObjectEntity::getRiskLevel, Collectors.counting()));
        riskObjectLevelStatistics.setTotalCount(riskObjects.size());
        riskObjectLevelStatistics.setLevel1Count(Optional.ofNullable(riskLevelMap.get(RiskDicConstant.RISK_OBJECT_LEVEL_1)).map(Long::intValue).orElse(0));
        riskObjectLevelStatistics.setLevel2Count(Optional.ofNullable(riskLevelMap.get(RiskDicConstant.RISK_OBJECT_LEVEL_2)).map(Long::intValue).orElse(0));
        riskObjectLevelStatistics.setLevel3Count(Optional.ofNullable(riskLevelMap.get(RiskDicConstant.RISK_OBJECT_LEVEL_3)).map(Long::intValue).orElse(0));
        riskObjectLevelStatistics.setLevel4Count(Optional.ofNullable(riskLevelMap.get(RiskDicConstant.RISK_OBJECT_LEVEL_4)).map(Long::intValue).orElse(0));
        return riskObjectLevelStatistics;
    }

    @Override
    public RiskHidCountStatistics calculateRiskHidCountStatistics(RiskHidCountStatisticsTypeEnum type) {
        List<RiskHidHiddenDangerEntity> hidList = riskHidHiddenDangerService.lambdaQuery()
                .select(RiskHidHiddenDangerEntity::getHidLevel, RiskHidHiddenDangerEntity::getHidSource, RiskHidHiddenDangerEntity::getHidStatus)
                .list();
        Map<Integer, Long> countMap = hidList.stream().collect(Collectors.groupingBy(type.getFunction(), Collectors.counting()));
        List<SysDictItem> dictItemList = DictResolver.getItemsByType(type.getDictEnum());
        RiskHidCountStatistics riskHidCountStatistics = new RiskHidCountStatistics();
        for (SysDictItem dictItem : dictItemList) {
            Integer code = Integer.valueOf(dictItem.getCode());
            String name = dictItem.getName();
            riskHidCountStatistics.addData(name, Optional.ofNullable(countMap.get(code)).map(Long::intValue).orElse(0));
        }
        return riskHidCountStatistics;
    }

    @Override
    public LineStatistics calculateRiskTaskTrendStatistics(RiskStatisticsCycleEnum cycle) {
        List<String> legendData = riskTransferAuthService.getRiskOrgStr();
        Date beginTime = RiskStatisticsCycleEnum.getBeginDate(cycle);
        Date endTime = new Date();

        List<RiskMeasureTaskRecordEntity> taskList = riskMeasureTaskRecordService.lambdaQuery()
                .ge(RiskMeasureTaskRecordEntity::getTaskHandleTime, beginTime)
                .lt(RiskMeasureTaskRecordEntity::getTaskHandleTime, endTime)
                .select(RiskMeasureTaskRecordEntity::getOrgId, RiskMeasureTaskRecordEntity::getTaskHandleTime)
                .list();

        LineStatisticsHelper<RiskMeasureTaskRecordEntity> lineStatisticsHelper = new LineStatisticsHelper<>();
        lineStatisticsHelper.setBeginTime(beginTime);
        lineStatisticsHelper.setEndTime(endTime);
        lineStatisticsHelper.setData(taskList);
        lineStatisticsHelper.setLegendData(legendData);
        lineStatisticsHelper.setHandlerDateFun(RiskMeasureTaskRecordEntity::getTaskHandleTime);
        lineStatisticsHelper.setGroupFun(RiskMeasureTaskRecordEntity::getOrgIdStr);
        lineStatisticsHelper.setStepFun(preDate -> DateUtil.offset(preDate, RiskStatisticsCycleEnum.getDateField(cycle), 1));
        lineStatisticsHelper.setXDataFun(date -> RiskStatisticsCycleEnum.getDateFormat(cycle, date));

        return lineStatisticsHelper.doStatistics();
    }

    @Override
    public LineStatistics calculateRiskHidRectifyTrendStatistics(RiskStatisticsCycleEnum cycle) {
        List<String> legendData = riskTransferAuthService.getRiskOrgStr();
        Date beginTime = RiskStatisticsCycleEnum.getBeginDate(cycle);
        Date endTime = new Date();
        List<RiskHidHiddenDangerEntity> hidList = riskHidHiddenDangerService.lambdaQuery()
                .ge(RiskHidHiddenDangerEntity::getReportDate, beginTime)
                .lt(RiskHidHiddenDangerEntity::getReportDate, endTime)
                .select(RiskHidHiddenDangerEntity::getOrgId, RiskHidHiddenDangerEntity::getReportDate)
                .list();

        LineStatisticsHelper<RiskHidHiddenDangerEntity> lineStatisticsHelper = new LineStatisticsHelper<>();
        lineStatisticsHelper.setBeginTime(beginTime);
        lineStatisticsHelper.setEndTime(endTime);
        lineStatisticsHelper.setData(hidList);
        lineStatisticsHelper.setLegendData(legendData);
        lineStatisticsHelper.setHandlerDateFun(RiskHidHiddenDangerEntity::getReportDate);
        lineStatisticsHelper.setGroupFun(t -> DictResolver.getItemLabelByValue(AdminDictEnum.sys_company, t.getOrgId()));
        lineStatisticsHelper.setStepFun(date -> DateUtil.offset(date, RiskStatisticsCycleEnum.getDateField(cycle), 1));
        lineStatisticsHelper.setXDataFun(date -> RiskStatisticsCycleEnum.getDateFormat(cycle, date));
        return lineStatisticsHelper.doStatistics();
    }

    @Override
    public RiskHidStatusStatistics calculateRiskHidStatistics(RiskStatisticsCycleEnum cycle) {
        RiskHidStatusStatistics riskHidStatusStatistics = new RiskHidStatusStatistics();

        Date beginTime = RiskStatisticsCycleEnum.getBeginDate(cycle);
        Date endTime = new Date();
        List<RiskHidHiddenDangerEntity> hidList = riskHidHiddenDangerService.lambdaQuery()
                .ge(RiskHidHiddenDangerEntity::getReportDate, beginTime)
                .lt(RiskHidHiddenDangerEntity::getReportDate, endTime)
                .select(RiskHidHiddenDangerEntity::getHidStatus, RiskHidHiddenDangerEntity::getHidLevel, RiskHidHiddenDangerEntity::getReportDate)
                .list();
        Map<Integer, List<RiskHidHiddenDangerEntity>> hidStatusMap = hidList.stream().collect(Collectors.groupingBy(RiskHidHiddenDangerEntity::getHidStatus));
        riskHidStatusStatistics.setRectifyCount(Optional.ofNullable(hidStatusMap.get(HidDicConstant.HIDDEN_DANGER_STATUS_RECTIFY)).map(List::size).orElse(0));
        riskHidStatusStatistics.setWaitCheckCount(Optional.ofNullable(hidStatusMap.get(HidDicConstant.HIDDEN_DANGER_STATUS_WAIT_CHECK)).map(List::size).orElse(0));
        riskHidStatusStatistics.setPostponeRectifyCount(Optional.ofNullable(hidStatusMap.get(HidDicConstant.HIDDEN_DANGER_STATUS_POSTPONE_RECTIFY)).map(List::size).orElse(0));
        riskHidStatusStatistics.setExpiredCount(Optional.ofNullable(hidStatusMap.get(HidDicConstant.HIDDEN_DANGER_STATUS_EXPIRED)).map(List::size).orElse(0));
        riskHidStatusStatistics.setCheckCount(Optional.ofNullable(hidStatusMap.get(HidDicConstant.HIDDEN_DANGER_STATUS_CHECK)).map(List::size).orElse(0));

        List<SysDictItem> hidStatusDic = DictResolver.getItemsByType(RiskSysDictEnum.hidden_danger_status);
        Map<Integer, List<Integer>> dataMap = new HashMap<>();
        for (SysDictItem dictItem : hidStatusDic) {
            riskHidStatusStatistics.addName(dictItem.getName());
            Integer code = Integer.valueOf(dictItem.getCode());
            List<RiskHidHiddenDangerEntity> hidStatusList = hidStatusMap.get(code);
            Integer generalHidCount = 0;
            Integer majorHidCount = 0;
            if (CollectionUtils.isNotEmpty(hidStatusList)) {
                Map<Integer, Long> countMap = hidStatusList.stream().collect(Collectors.groupingBy(RiskHidHiddenDangerEntity::getHidLevel, Collectors.counting()));
                generalHidCount = Optional.ofNullable(countMap.get(HidDicConstant.DANGER_LEVEL_GENERAL)).map(Long::intValue).orElse(0);
                majorHidCount = Optional.ofNullable(countMap.get(HidDicConstant.DANGER_LEVEL_MAJOR)).map(Long::intValue).orElse(0);
            }
            List<Integer> generalDataList = Optional.ofNullable(dataMap.get(HidDicConstant.DANGER_LEVEL_GENERAL)).orElseGet(ArrayList::new);
            generalDataList.add(generalHidCount);
            dataMap.put(HidDicConstant.DANGER_LEVEL_GENERAL, generalDataList);

            List<Integer> majorDataList = Optional.ofNullable(dataMap.get(HidDicConstant.DANGER_LEVEL_MAJOR)).orElseGet(ArrayList::new);
            majorDataList.add(majorHidCount);
            dataMap.put(HidDicConstant.DANGER_LEVEL_MAJOR, majorDataList);
        }
        dataMap.forEach((k, v) -> {
            riskHidStatusStatistics.addData(DictResolver.getItemLabelByValue(RiskSysDictEnum.danger_level, k), v);
        });
        return riskHidStatusStatistics;
    }
}
